﻿using System;

using Microsoft.VisualStudio.TestTools.UnitTesting;

using advadev.CanOpen;


namespace advadev.CanOpen.UnitTests
{

    /// <summary>
    /// Represents the network management node guarding message write transfer
    /// unit tests
    /// </summary>
    [TestClass]
    public class NetworkManagementNodeGuardingMessageWriteTransferTest : ICanOpenObjectDictionaryContainer
    {

        #region constructor tests
        /// <summary>
        /// Constructor test
        /// </summary>
        [TestMethod]
        public void ConstructorTest()
        {
            // initialization
            bool toggleBitSet = false;
            NetworkManagementControlState networkManagementControlState = NetworkManagementControlState.Unkown;
            NetworkManagementNodeGuardingMessageWriteTransfer testObject = null;

            // node id out of range parameter
            try
            {
                testObject = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, 0);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
            try
            {
                testObject = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, 128);
                Assert.Fail();
            }
            catch (ArgumentOutOfRangeException)
            {
            }
            catch
            {
                Assert.Fail();
            }
        }
        #endregion constructor tests


        #region slave side tests
        /// <summary>
        /// Slave side test
        /// </summary>
        [TestMethod]
        public void SlaveSideTest()
        {
            // initialization
            byte nodeId = 103;
            UInt16 cobId = 0x100;
            bool toggleBitSet = false;
            NetworkManagementControlState networkManagementControlState = NetworkManagementControlState.Unkown;
            NetworkManagementNodeGuardingMessageWriteTransfer testObject = null;

            // test with toggle bit set and control state operational
            toggleBitSet = true;
            networkManagementControlState = NetworkManagementControlState.Operational;
            testObject = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, nodeId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(0x767, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x85, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)1, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            toggleBitSet = true;
            networkManagementControlState = NetworkManagementControlState.Operational;
            testObject = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, nodeId, cobId);
            testObject.Start();
            Assert.AreEqual(false, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(1, testObject.PendingSendMessages.Count);
            Assert.AreEqual(cobId + nodeId, testObject.PendingSendMessages[0].CanId);
            Assert.AreEqual(0x85, testObject.PendingSendMessages[0].Byte0);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte1);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte2);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte3);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte4);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte5);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte6);
            Assert.AreEqual(0x00, testObject.PendingSendMessages[0].Byte7);
            Assert.AreEqual((uint)1, testObject.PendingSendMessages[0].Length);
            testObject.ContinueAfterSendingMessages();
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion slave side tests


        #region is network management node guarding message write transfer request tests
        /// <summary>
        /// Is network management node guarding message write transfer request
        /// test
        /// </summary>
        [TestMethod]
        public void IsNetworkManagementNodeGuardingMessageWriteTransferRequestTest()
        {
            // initialization
            bool isNetworkManagementNodeGuardingMessageWriteTransferRequest = false;
            byte receivedToggleBit = 0;
            NetworkManagementControlState receivedNetworkManagementControlState = NetworkManagementControlState.Unkown;
            NetworkManagementNodeGuardingMessageReceivedEventHandler handler = new NetworkManagementNodeGuardingMessageReceivedEventHandler((object sender, NetworkManagementNodeGuardingMessageReceivedEventArgs args) =>
            {
                receivedToggleBit = args.ToggleBit;
                receivedNetworkManagementControlState = args.NetworkManagementControlState;
            });
            NetworkManagementNodeGuardingMessageWriteTransfer testObject = null;

            // test with valid received can open message
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(new CanOpenMessage(0x767, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);

            // test with wrong COB-ID
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(new CanOpenMessage(0x167, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, handler);
            Assert.AreNotEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNull(testObject);

            // test with handler is null
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(new CanOpenMessage(0x767, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00), out testObject, null);
            Assert.AreEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
        }
        #endregion is network management node guarding message write transfer request tests


        #region master side tests
        /// <summary>
        /// Master side test
        /// </summary>
        [TestMethod]
        public void MasterSideTest()
        {
            // initialization
            bool isNetworkManagementNodeGuardingMessageWriteTransferRequest = false;
            byte nodeId = 103;
            UInt16 cobId = 0x100;
            bool toggleBitSet = false;
            bool receivedToggleBitSet = false;
            NetworkManagementControlState receivedNetworkManagementControlState = NetworkManagementControlState.Unkown;
            NetworkManagementControlState networkManagementControlState = NetworkManagementControlState.Unkown;
            NetworkManagementNodeGuardingMessageReceivedEventHandler handler = new NetworkManagementNodeGuardingMessageReceivedEventHandler((object sender, NetworkManagementNodeGuardingMessageReceivedEventArgs args) =>
            {
                receivedToggleBitSet = (args.ToggleBit == 0 ? false : true);
                receivedNetworkManagementControlState = args.NetworkManagementControlState;
            });
            NetworkManagementNodeGuardingMessageWriteTransfer testObject = null;
            NetworkManagementNodeGuardingMessageWriteTransfer slaveTransfer = null;

            // test with toggle bit set and control state operational
            receivedToggleBitSet = false;
            receivedNetworkManagementControlState = NetworkManagementControlState.Unkown;
            toggleBitSet = true;
            networkManagementControlState = NetworkManagementControlState.Operational;
            slaveTransfer = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, nodeId);
            slaveTransfer.Start();
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(slaveTransfer.PendingSendMessages[0], out testObject, handler);
            Assert.AreEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(toggleBitSet, receivedToggleBitSet);
            Assert.AreEqual(networkManagementControlState, receivedNetworkManagementControlState);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test with changed COB-ID
            receivedToggleBitSet = false;
            receivedNetworkManagementControlState = NetworkManagementControlState.Unkown;
            toggleBitSet = true;
            networkManagementControlState = NetworkManagementControlState.Operational;
            slaveTransfer = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, nodeId, cobId);
            slaveTransfer.Start();
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(slaveTransfer.PendingSendMessages[0], out testObject, cobId, handler);
            Assert.AreEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(toggleBitSet, receivedToggleBitSet);
            Assert.AreEqual(networkManagementControlState, receivedNetworkManagementControlState);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);

            // test without handler
            receivedToggleBitSet = false;
            receivedNetworkManagementControlState = NetworkManagementControlState.Unkown;
            toggleBitSet = true;
            networkManagementControlState = NetworkManagementControlState.Operational;
            slaveTransfer = new NetworkManagementNodeGuardingMessageWriteTransfer(toggleBitSet, networkManagementControlState, nodeId);
            slaveTransfer.Start();
            isNetworkManagementNodeGuardingMessageWriteTransferRequest = NetworkManagementNodeGuardingMessageWriteTransfer.IsNetworkManagementNodeGuardingMessageWriteTransfer(slaveTransfer.PendingSendMessages[0], out testObject, null);
            Assert.AreEqual(true, isNetworkManagementNodeGuardingMessageWriteTransferRequest);
            Assert.IsNotNull(testObject);
            testObject.Start();
            Assert.AreEqual(false, receivedToggleBitSet);
            Assert.AreEqual(NetworkManagementControlState.Unkown, receivedNetworkManagementControlState);
            Assert.AreEqual(true, testObject.TransferComplete);
            Assert.IsNull(testObject.AbortCode);
            Assert.IsNotNull(testObject.PendingSendMessages);
            Assert.AreEqual(0, testObject.PendingSendMessages.Count);
        }
        #endregion master side tests


        #region ICanOpenObjectDictionaryContainer
        /// <summary>
        /// Gets the node id of the can open object dictionary container
        /// </summary>
        byte ICanOpenObjectDictionaryContainer.NodeId
        {
            get
            {
                return 103;
            }
        }

        /// <summary>
        /// Gets the can open object with the given index as can open data field
        /// object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index as data field object or
        /// null
        /// </returns>
        ICanOpenDataFieldObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index)
        {
            return null;
        }

        /// <summary>
        /// Gets the can open object with the given index and sub index as can
        /// open value object
        /// </summary>
        /// <param name="index">
        /// Index of the can open object to get
        /// </param>
        /// <param name="subIndex">
        /// Sub index of the can open object to get
        /// </param>
        /// <returns>
        /// The can open object with the given index and sub index as value
        /// object or null
        /// </returns>
        ICanOpenValueObject ICanOpenObjectDictionaryContainer.GetCanOpenObject(UInt16 index, byte subIndex)
        {
            return null;
        }
        #endregion ICanOpenObjectDictionaryContainer

    }

}
